#include "TurnLampStateMachine.h"
#include "F3LampInterfaces.h"
#include "LampManager.h"


void InitTurnStateMachine(void)
{
    InitTurnLampSleepStateMachine();
    InitNormalStateMachine();
    InitRibbonLeTurnLampStateMachine();
    InitRibbonPosnStateMachine();
}

static void exitLastState(UsageModeState lastState)
{
    switch (lastState)
    {
        case UsageModeState_Normal:
        {
            g_NormalStateMachine.sm_.Exit();
            break;
        }

        case UsageModeState_Ribbon:
        {
            g_RibbonLeTurnLampStateMachine.sm_.Exit();
            g_RibbonPosnStateMachine.sm_.Exit();
            break;
        }

        case UsageModeState_Sleep:
        {
            g_TurnLampSleepStateMachine.sm_.Exit();
            break;
        }

        default:
            break;
    }
}

static void entryNewState(UsageModeState newState)
{
    switch (newState)
    {
        case UsageModeState_Normal:
        {
            g_NormalStateMachine.sm_.Entry();
            break;
        }

        case UsageModeState_Ribbon:
        {
            g_RibbonLeTurnLampStateMachine.sm_.Entry();
            g_RibbonPosnStateMachine.sm_.Entry();
            break;
        }

        case UsageModeState_Sleep:
        {
            g_TurnLampSleepStateMachine.sm_.Entry();
            break;
        }

        default:
            break;
    }
}

static void excuteNewState(UsageModeState newState)
{
    switch(newState)
    {
        case UsageModeState_Normal:
        {
            g_NormalStateMachine.sm_.Excute();
            break;
        }

        case UsageModeState_Ribbon:
        {
            g_RibbonLeTurnLampStateMachine.sm_.Excute();
            g_RibbonPosnStateMachine.sm_.Excute();
            break;
        }

        case UsageModeState_Sleep:
        {
            g_TurnLampSleepStateMachine.sm_.Excute();
            break;
        }

        default:
            break;
    }
}

void TurnStateMachineExecute(void)
{
    if(g_TurnNewState.usageModeState_ != g_TurnLastState.usageModeState_)
    {
        exitLastState(g_TurnLastState.usageModeState_);
        entryNewState(g_TurnNewState.usageModeState_);
    }
    excuteNewState(g_TurnNewState.usageModeState_);
}


void TurnNormalStateTransition(void)
{
    TurnLampOccupyStsFlag turnLampFlag = Get_CANSIG_TurnLampOccupySts();
    bool turnLampOccupy = turnLampFlag == TurnLampOccupySts_LeTurn || turnLampFlag == TurnLampOccupySts_ALL || Is_TL_EN();
    bool DaytimeLampOn = Get_CANSIG_DaytimeLampOnCmd() == OnOff_On;
    bool PosnLampOn = Get_CANSIG_FLPosnLampOnCmd() == OnOff_On;

    updateFrntTurnLampSnapshot(PosnLampOn, DaytimeLampOn, &g_DayTimeAndPosLampView.lastModel_.snapshot_, &g_DayTimeAndPosLampView.model_->snapshot_);

    if(turnLampOccupy)
    {
        if(!Is_TL_Flow())
        {
            g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_Flow;
        }
        else
        {
            g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_Flicker;
        }
    }
    else
    {
        if(DaytimeLampOn && PosnLampOn)
        {
            if(g_TurnLastState.normalState_ == NormalStateLeFrntTurnLamp_DayTime)
            {
                g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButPosn;
            }
            else if(g_TurnLastState.normalState_ == NormalStateLeFrntTurnLamp_Posn)
            {
                g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButDayTime;
            }
            else if(NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButDayTime == g_TurnLastState.normalState_ || NormalStateLeFrntTurnLamp_DayTimeAndPosBoth_ButPosn == g_TurnLastState.normalState_)
            {
                //                g_TurnLastState.normalState_ = g_TurnLastState.normalState_;
            }
            else if(NormalStateLeFrntTurnLamp_Flicker == g_TurnLastState.normalState_ || NormalStateLeFrntTurnLamp_Flow == g_TurnLastState.normalState_)
            {
                g_TurnNewState.normalState_ = getNormalStateWithFrntTurnLampSnapshot(&g_DayTimeAndPosLampView.lastModel_.snapshot_);
            }
            else
            {
                g_TurnNewState.normalState_ = getNormalStateWithFrntTurnLampSnapshot(&g_DayTimeAndPosLampView.lastModel_.snapshot_);
                //                g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_Default;
            }
        }
        else if(DaytimeLampOn)
        {
            g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_DayTime;
        }
        else if(PosnLampOn)
        {
            g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_Posn;
        }
        else
        {
            g_TurnNewState.normalState_ = NormalStateLeFrntTurnLamp_Default;
        }
    }
}

static void RibbonLeTurnStateTransition(bool turnLampOccupy)
{
    if(turnLampOccupy)
    {
        if(!Is_TL_Flow())
        {
            g_TurnNewState.ribbonLeTurnLampState_ = RibbonLeTurnLamp_Flow;
        }
        else
        {
            g_TurnNewState.ribbonLeTurnLampState_ = RibbonLeTurnLamp_Flicker;
        }
    }
    else
    {
        g_TurnNewState.ribbonLeTurnLampState_ = RibbonLeTurnLamp_Free;
    }
}

static void calculatePosnShowEffect(void)
{
    RibbonEffectSel show = Get_CANSIG_FrntRibbonLampEffectSel();
    g_RibbonView.model_->frntRibbonLampEffectSt_ = show;
    switch(show)
    {
        case RibbonEffect_Effect_1:
        case RibbonEffect_Effect_2:
        case RibbonEffect_Effect_3:
        case RibbonEffect_Effect_4:
        {
            g_TurnNewState.ribbonPosnEffectShowState_ = RibbonPosnEffectShowState_Unlock;
            break;
        }

        case RibbonEffect_Effect_7:
        {
            g_TurnNewState.ribbonPosnEffectShowState_ = RibbonPosnEffectShowState_All;
            break;
        }


        case RibbonEffect_Effect_8:
        case RibbonEffect_Effect_9:
        case RibbonEffect_Effect_a:
        case RibbonEffect_Effect_b:
        {
            g_TurnNewState.ribbonPosnEffectShowState_ = RibbonPosnEffectShowState_Lock;
            break;
        }

        case RibbonEffect_Effect_d:
        {
            g_TurnNewState.ribbonPosnEffectShowState_ = RibbonPosnEffectShowState_Off;
            break;
        }
        default:
        {
            g_TurnNewState.ribbonPosnEffectShowState_ = RibbonPosnEffectShowState_Default;
            break;
        }
    }
}

static void RibbonPosnStateTransition(RibbonCtrlCmd cmd)
{
    switch(cmd)
    {
        case RibbonCtrl_Initial:
        case RibbonCtrl_NoRequest:
        case RibbonCtrl_Off:
        case RibbonCtrl_Invalid:
        {
            g_TurnNewState.ribbonPosnCtrlState_ = RibbonPosnCtrlState_Off;
            break;
        }

        case RibbonCtrl_On:
        case RibbonCtrl_Pause:
        {
            g_TurnNewState.ribbonPosnCtrlState_ = RibbonPosnCtrlState_On;
            calculatePosnShowEffect();
            break;
        }

        case RibbonCtrl_Again:
        {
            g_TurnNewState.ribbonPosnCtrlState_ = RibbonPosnCtrlState_Again;
            break;
        }

        default:
        {
            g_TurnNewState.ribbonPosnCtrlState_ = RibbonPosnCtrlState_Off;
            break;
        }

    }
}



static void calculateRobbinPosnAnimationModel(bool turnLampOccupy, RibbonCtrlCmd posnCtrlcmd)
{
    if(turnLampOccupy)
    {
        g_RibbonAnimationModel.posnMode_ = LeTurnLampOccupy;
    }
    else if(posnCtrlcmd == RibbonCtrl_Pause)
    {
        g_RibbonAnimationModel.posnMode_ = Pause;
    }
    else
    {
        RibbonEffectMod mode = Get_CANSIG_FrntRibbonLampEffectModSet();
        switch(mode)
        {
            case RibbonEffectMod_Initial:
            {
                g_RibbonAnimationModel.posnMode_ = Init;    // Ignore Init
                break;
            }

            case RibbonEffectMod_Off:
            case RibbonEffectMod_Hold:
            {
                g_RibbonAnimationModel.posnMode_ = Hold;    // Off action as Hold
                break;
            }

            case RibbonEffectMod_Repeat:
            {

                g_RibbonAnimationModel.posnMode_ = Repeat;
                break;
            }

            default:
            {
                g_RibbonAnimationModel.posnMode_ = Default; //Unknown
                break;
            }
        }
    }
}


void TurnRibbonStateTransition(void)
{
    TurnLampOccupyStsFlag turnLampFlag = Get_CANSIG_TurnLampOccupySts();
    bool turnLampOccupy = turnLampFlag == TurnLampOccupySts_LeTurn || turnLampFlag == TurnLampOccupySts_ALL || Is_TL_EN();
    RibbonLeTurnStateTransition(turnLampOccupy);

    RibbonCtrlCmd posnCtrlcmd = Get_CANSIG_FrntRibbonLampEffectCtrlCmd();
    RibbonPosnStateTransition(posnCtrlcmd);
    calculateRobbinPosnAnimationModel(turnLampOccupy, posnCtrlcmd);
}

void TurnSleepStateTransition(void)
{
    //no more child state
}